package model;

import java.util.ArrayList;
import java.util.List;
import util.Converter;

/**
 * A piece is a combination of sequences.
 */
public class Piece {

	private List<Sequence> sequences;
	private String name;
	private int length;
	private int tempo;

	/**
	 * Creates a new piece with an initial blank sequence added.
	 */
	public static Piece createNewPiece(String name, int length) {
		Piece piece = new Piece(name, length);
		piece.addSequence(new Sequence(length));

		return piece;
	}

	/**
	 * Creates the sample piece used at the program's startup.
	 */
	public static Piece createSamplePiece() {
		Piece piece = Converter.convertMPCSong("/data/mariopaintsample.txt");

		return piece;
	}

	//Blank Piece
	public Piece(String name, int length) {
		this(name, new ArrayList<Sequence>(), length, 1000);
	}

	public Piece(String name, List<Sequence> sequences, int length, int tempo) {
		this.name = name;
		this.sequences = sequences;
		this.length = length;
		this.tempo = tempo;
	}

	/**
	 * Adds the given sequence to the end of the piece
	 *
	 * @param sequence The sequence to add
	 */
	public void addSequence(Sequence sequence) {
		sequences.add(sequence);
	}

	/**
	 * Adds the given sequence to the piece at the given index and shifts all
	 * subsequent sequences after it.
	 *
	 * @param sequence The sequence to add
	 * @param index The index to add it at
	 */
	public void addSequence(Sequence sequence, int index) {
		sequences.add(index, sequence);
	}

	/**
	 * Gets a Sequence at the given position
	 *
	 * @param index
	 * @return
	 */
	public Sequence getSequence(int index) {
		return sequences.get(index);
	}

	/**
	 * Remove the given sequence from the piece
	 *
	 * @param sequence The sequence to remove
	 */
	public void removeSequence(Sequence sequence) {
		sequences.remove(sequence);
	}

	/**
	 * Remove the sequence located at the given index
	 *
	 * @param index The index of the sequence to remove
	 */
	public void removeSequence(int index) {
		sequences.remove(index);
	}

	public List<Sequence> getSequences() {
		return sequences;
	}

	public int getSequenceCount() {
		return sequences.size();
	}

	/**
	 * Sets the name of the piece to the given String
	 *
	 * @param name The new name of the piece
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Returns the name of this piece.
	 *
	 * @return The name of this piece
	 */
	public String getName() {
		return name;
	}

	/**
	 * Returns the length of the piece.
	 * @return The length
	 */
	public int getLength() {
		return length;
	}

	/**
	 * Returns the speed this piece is played at
	 * @return
	 */
	public int getTempo() {
		return tempo;
	}

	public void setTempo(int tempo) {
		this.tempo = tempo;
	}

	/**
	 * Adjusts this Piece's length to match the given length by cutting off or
	 * extending every sequence accordingly.<br>
	 * This does not modify the actual Piece, instead it returns a new Piece
	 * identical to this piece in every way except with new sequences.
	 */
	public Piece adjustLength(int newLength) {
		//Create a copy of the sequences but cut-off or extend them according to the new length.
		List<Sequence> newSequences = new ArrayList<>();
		for(Sequence sequence : sequences) {
			int[] notes = sequence.getAllNotes();
			int[] newNotes = new int[newLength];
			for(int i = 0; i < newNotes.length && i < notes.length; i++) {
				newNotes[i] = notes[i];
			}

			newSequences.add(
				new Sequence(sequence.getInstrument(), newNotes, sequence.getVolume())
			);
		}

		Piece piece = new Piece(
			this.getName(), newSequences, newLength, this.getTempo()
		);

		//Return the modified piece.
		return piece;
	}

}
